package engine.system;


import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import engine.event.key.JKeyboardListener;
import engine.event.mouse.JMouseListener;
import engine.input.JKeyboard;
import engine.input.JMouse;
import engine.j2d.Font;
import engine.j2d.Graphics;
import engine.j2d.TextureLoader;
import game.ai.World;

public abstract class Window implements Engine
{
	private boolean gameRunning = true;
	public static int width;
	public static int height;
	private TextureLoader textureLoader;
	protected String title;
	private long lastFPS;
	private int recordedFPS;
	private int fps;
	public static boolean WINDOW_CLOSING = false;
	private Graphics g = new Graphics();
	private String bpp;
	private long delta_t = 0;
	private long prev_ticks = Sys.getTime();
	private long ticks;
//	public static float delta_t = 0.0f;
	public static World world = World.getInstance();

	protected Window()
	{
		// hide constructor
	}

	public void setFullscreen(boolean fullscreen)
	{
		try
		{
			Display.setFullscreen(fullscreen);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public TextureLoader getTextureLoader()
	{
		return textureLoader;
	}

	public static long getTime()
	{
		return (Sys.getTime() * 1000) / Sys.getTimerResolution();
	}

	public void setTitle(String title)
	{
		this.title = title;
		if (Display.isCreated())
		{
			Display.setTitle(title);
		}
	}

	public void setResolution(int x, int y)
	{
		width = x;
		height = y;
	}

	public void setBpp(String bpp)
	{
		this.bpp = bpp;
	}

	private boolean setDisplayMode()
	{
		try
		{
			DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(
					width, height, -1, -1, -1, -1, 60, 60);

			org.lwjgl.util.Display.setDisplayMode(dm, new String[] {
					"width=" + width, "height=" + height, "freq=" + 60,
					"bpp=" + bpp });
			JMouse.init(height);
			return true;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.out.println("Kann nicht in fullscreen mode arbeiten");
		}
		return false;
	}
	public void initEngine()
	{
		setDisplayMode();
		try
		{
			Display.create();
			Keyboard.create();
		}
		catch (LWJGLException e)
		{
			e.printStackTrace();
		}
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glShadeModel(GL11.GL_SMOOTH);
		GL11.glDisable(GL11.GL_DEPTH_TEST);
		GL11.glDisable(GL11.GL_LIGHTING);
		GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		GL11.glClearDepth(1.0f);
		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glViewport(0, 0, width, height);
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, width, height, 0, 1, -1);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		world.clear();
		world.initialise();
		prev_ticks = Sys.getTime();
		init();
		g.setFont(Font.FELIX);
		runEngine();
	}

	private void runEngine()
	{
		while (gameRunning)
		{
			setFPS();
			// clear window
			GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
			GL11.glLoadIdentity();
			// run, logic and paint
			if (delta_t > 0) {
				world.update(delta_t / 1000f);
			} else {
				Thread.yield();
			}
			world.runNextStep();
			run();
			JMouse.fireMouse();
			JKeyboard.fireKeyboard();
			world.render(g);
			paint(g);
			// update window
			Display.update();
			
			if (Display.isCloseRequested()
					|| Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
			{
				gameRunning = false;
				WINDOW_CLOSING = true;
				Display.destroy();
			}
		}
		world.clear();
	}

	protected void setFPS()
	{
		ticks = System.currentTimeMillis();
		delta_t = ticks - prev_ticks;
		prev_ticks = ticks;
		if (ticks - lastFPS > 1000)
		{
			lastFPS = ticks;
			recordedFPS = fps;
			fps = 0;
		}
		fps++;
	}

	public void windowClosed()
	{
		// do nothing
	}
	public int getFPS()
	{
		return recordedFPS;
	}
	public static void addMouseListener(JMouseListener l)
	{
		JMouse.getDisplay().addMouseEventListener(l);
	}
	public static void addKeyboardListener(JKeyboardListener l)
	{
		JKeyboard.getJDisplay().addKeyEventListener(l);
	}
	public static void removeMouseListener(JMouseListener l)
	{
		JMouse.getDisplay().removeMouseEventListener(l);
	}
	public static void removeKeyboardListener(JKeyboardListener l)
	{
		JKeyboard.getJDisplay().removeKeyEventListener(l);
	}
}
